#ifndef __NETWORK_H
#define __NETWORK_H

#include "utils.h"

#include <sys/socket.h> // 套接字 API
#include <netinet/in.h> // Internet 地址族
#include <arpa/inet.h>  // 定义 inet_addr

/**
 * @brief 用户信息结构体
 *
 */
typedef struct
{
    char pwd[MAX_PATH_LEN]; /**< 用户当前工作目录 */
    char name[256];         /**< 用户名 */
    char password[256];     /**< 密码 */
    char jwt_token[1024];   /**< JWT token */
    bool if_login;          /**< 是否是请求登录 */
} UserInfo_t;

/**
 * @brief 客户端信息结构体
 * 包括地址、端口、套接字、活跃时间等
 */
typedef struct client_s
{
    struct sockaddr_in addr; /**< socket地址 */
    socklen_t addr_len;      /**< socket地址长度 */
    char ip[16];             /**< ip地址 */
    int port;                /**< 端口 */
    int socket_fd;           /**< 套接字文件描述符 */
    int tunnel_fd;           /**< 隧道套接字文件描述符 */
    time_t last_active_time; /**< 最后活跃时间 */
    char cur_path[256];      /**< 用户当前工作目录 */
    UserInfo_t user_info;    /**< 用户信息 */
} Client_t;

/**
 * @brief 客户端列表结构体
 *  存储客户端信息结构体数组
 */
typedef struct
{
    Client_t *clients; /**< 客户端信息结构体数组 */
    int count;         /**< 客户端数量 */
    int max_clients;   /**< 最大客户端数量 */
} ClientList_t;

/**
 * @brief 服务端信息结构体和隧道信息结构体
 * 包括地址、端口、套接字、最大连接数等
 */
typedef struct server_s
{
    struct sockaddr_in addr; /**< socket地址 */
    socklen_t addr_len;      /**< socket地址长度 */
    char ip[16];             /**< ip地址 */
    int port;                /**< 端口 */
    int socket_fd;           /**< 套接字文件描述符 */
    int max_connections;     /**< 最大连接数 */
    int if_reuse;            /**< 是否可重用端口 */
} Server_t, Tunnel_t;

/**
 * @brief 服务器列表结构体
 *  存储主服务器server及其他用于上传下载的服务器tunnel
 */
typedef struct
{
    Server_t server;  /**< 主服务器 */
    int tunnel_count; /**< 隧道数量 */
    Tunnel_t *tunnel; /**< 隧道 */
} ServerCluster_t;

/**
 * @brief 初始化服务器信息结构体
 * 从配置文件结构体加载参数
 * @param server 服务器信息结构体
 * @param config 配置文件结构体
 * @return int
 *  @retval -1 加载失败
 *  @retval 0 成功
 */
int initServer(Server_t *server, const ServerConfig_t *config);

/**
 * @brief 初始化TCP连接
 *
 * @param server 服务器信息结构体
 * @return int
 *  @retval -1 连接失败
 *  @retval 0 连接成功
 */
int initTcpSocket(Server_t *server);

/**
 * @brief 初始化客户端表
 *
 * @param max_clients
 * @return ClientList_t*
 */
ClientList_t *initClientList(int max_clients);

/**
 * @brief 释放客户端表结构体
 *
 * @param client_list
 */
void freeClientList(ClientList_t *client_list);

/**
 * @brief 接收TCP连接
 *
 * @param server 服务器信息结构体
 * @param client 客户端信息结构体
 * @return int 返回是否连接成功
 *  @retval -1 连接失败
 *  @retval 0 连接成功
 */
int acceptConnection(Server_t *server, Client_t *client);

/**
 * @brief 接收隧道TCP连接
 *
 * @param tunnel 隧道信息结构体
 * @param client 客户端信息结构体
 * @return int 返回是否连接成功
 *  @retval -1 连接失败
 *  @retval 0 连接成功
 */
int acceptTunnelConnection(Tunnel_t *tunnel, Client_t *client);

/**
 * @brief 关闭客户端连接
 *
 * @param client 客户端信息结构体
 */
void closeConnection(Client_t *client);

/**
 * @brief 更新客户端最后一次活跃时间
 *
 * @param client 客户端信息结构体
 */
void updateActiveTime(Client_t *client);

/**
 * @brief 循环发送数据
 * 内部循环使用send保证数据完全发送
 * @param sockfd 套接字文件描述符
 * @param buffer 缓冲区
 * @param length 长度
 * @param flags 标志
 * @return ssize_t 返回发送的字节数
 */
ssize_t sendAll(int sockfd, const void *buffer, size_t length, int flags);

/**
 * @brief 循环接收数据
 * 内部循环使用recv保证数据完全接收
 * @param sockfd 套接字文件描述符
 * @param buffer 缓冲区
 * @param length 长度
 * @param flags 标志
 * @return ssize_t 返回接收的字节数
 */
ssize_t recvAll(int sockfd, void *buffer, size_t length, int flags);

/**
 * @brief 初始化服务器集群
 * 从配置文件结构体加载隧道参数信息，内部动态分配内存，根据隧道数量初始化隧道信息结构体数组
 * @param config 配置文件结构体，内部存储多个隧道ip和端口信息
 * @return ServerCluster_t*
 */
ServerCluster_t *initServerCluster(const ServerConfig_t *config);

/**
 * @brief 释放服务器集群结构体
 *
 * @param cluster 服务器集群结构体
 */
void freeServerCluster(ServerCluster_t *cluster);

#endif /* __NETWORK_H */